#include "StdAfx.h"
#include "AiPlayer.h"
#include <stdio.h>
#include "Observers.h"

AiPlayer::AiPlayer()
{
	Action = AiBrain::ACT_FOLD;

	PokerWindow = 0;
	PlayerInfo = 0;
	TableInfo = 0;
	MyPos = -1;
	RaiseCnt = 0;

	//initialize rects
	Rects.FoldBtn.T = 0.88827838827838827838827838827839;
	Rects.FoldBtn.L = 0.54068241469816272965879265091864;
	Rects.FoldBtn.R = 0.66414141414141414141414141414141;
	Rects.FoldBtn.B = 0.98717948717948717948717948717949;

	Rects.CallBtn.T = 0.88827838827838827838827838827839;
	Rects.CallBtn.L = 0.68181818181818181818181818181818;
	Rects.CallBtn.B = 0.98717948717948717948717948717949;
	Rects.CallBtn.R = 0.8270202020202020202020202020202;	

	Rects.RaiseBtn.T = 0.88827838827838827838827838827839;
	Rects.RaiseBtn.L = 0.83964646464646464646464646464646;
	Rects.RaiseBtn.B = 0.98717948717948717948717948717949;
	Rects.RaiseBtn.R = 0.98737373737373737373737373737374;
	

	Rects.FoldBtn.T = 0.88827838827838827838827838827839;
	Rects.FoldBtn.L = 0.54068241469816272965879265091864;
	Rects.FoldBtn.R = 0.66414141414141414141414141414141;
	Rects.FoldBtn.B = 0.98717948717948717948717948717949;

	Rects.RaiseEdit.T = 0.83882783882783882783882783882784; //0.81135531135531135531135531135531;
	Rects.RaiseEdit.L = 0.7790404040404040404040404040404;
	Rects.RaiseEdit.R = 0.81135531135531135531135531135531;
	Rects.RaiseEdit.B = 0.83882783882783882783882783882784 * 2 - 0.81135531135531135531135531135531; //0.83882783882783882783882783882784;
}


//---------------------------------------------------------------------------------------------------------------------------------------
inline RECT AiPlayer::RectFtoRect(RectF &iR) const
{
	//get window width and height
	RECT wr;
	::GetClientRect(PokerWindow, &wr);
	wr.bottom -= wr.top;
	wr.right -= wr.left;


	//translate from 0..1 coords to window coords
	RECT out;
	out.left = static_cast<long>(iR.L * wr.right);
	out.right = static_cast<long>(iR.R * wr.right);
	out.top = static_cast<long>(iR.T * wr.bottom);
	out.bottom = static_cast<long>(iR.B * wr.bottom);
	return out;
}


//---------------------------------------------------------------------------------------------------------------------------------------
inline HWND AiPlayer::ClickOnRect(RectF &iR) const
{
	if(!PokerWindow) return 0;

	//get cursor pos
	RECT r = RectFtoRect(iR);
	POINT p;
	p.x = (r.left + r.right)/2;
	p.y = (r.bottom + r.top)/2;
	
	ClientToScreen(PokerWindow, &p);

	
	//bring window to front
	HWND h = 0;
	do 
	{		
		SetForegroundWindow(PokerWindow);

		Sleep(200);


		//move cursor
		int t = MouseAnim.AnimateSync(p.x, p.y, 5, 5);
		if(t < 300)
			Sleep(300-t);
	
		
		h = ::WindowFromPoint(p);
		ScreenToClient(h, &p);
		
		
		//click on the center of the button
		INPUT inp[2];
		memset(inp,0,sizeof(inp));
		inp[0].type=INPUT_MOUSE;
		inp[0].mi.dwFlags=MOUSEEVENTF_LEFTDOWN;
		inp[0].mi.dx = p.x;
		inp[0].mi.dy = p.y;
		inp[1].type=INPUT_MOUSE;
		inp[1].mi.dwFlags=MOUSEEVENTF_LEFTUP;
		inp[1].mi.dx = p.x;
		inp[1].mi.dy = p.y;

		::SendInput(2, inp, sizeof(INPUT));

		
// 		LPARAM lparam = MAKELPARAM(p.x, p.y);
// 
// 		PostMessage(h, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
// 		PostMessage(h, WM_LBUTTONUP, MK_LBUTTON, lparam);
	} 
	while (::GetForegroundWindow() != PokerWindow && ::GetParent(::GetForegroundWindow()) != PokerWindow);


	//remove cursor from window's area
	GetWindowRect(PokerWindow, &r);
	int sw = GetSystemMetrics(SM_CXVIRTUALSCREEN);//desktop width
	int sh = GetSystemMetrics(SM_CYVIRTUALSCREEN) - 100;//desktop height
	
	//find the point not in the window
	bool find = false;
	int iters = 100;
	int line_width  = 100;
	int x = 0;
	int y = 0;
	do
	{	
		x = sw - line_width + (line_width*rand())/RAND_MAX;
		y = (sh*rand())/RAND_MAX;
		if(x < r.left || x > r.right)
		{
			find = true;
		}
		if(y < r.top || y > r.bottom)
		{
			find = true;
		}
		iters--;
	}
	while(!find && iters);
	if(x == 0) x = 1;
	if(y == 0) y = 1;

	if(find) MouseAnim.AnimateSync(x, y, 10, 10);

	return h;
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::Raise(const int iCount)
{
	if(!PokerWindow) return;

	//click on the edit box
	HWND h = ClickOnRect(Rects.RaiseEdit);
	
	
	//click edit box
	int textlength = 10;
	::PostMessage(h, WM_KEYDOWN, VK_HOME, 0);
	Sleep(10);
	::PostMessage(h, WM_KEYUP, VK_HOME, 0);
	for(int i=0; i<textlength; i++)
	{
		Sleep(10);
		::PostMessage(h, WM_KEYDOWN, VK_DELETE, 0);
		Sleep(10);
		::PostMessage(h, WM_KEYUP, VK_DELETE, 0);
	}
	

	//write text to edit box
	char buf[20];
	sprintf(buf, "%d", iCount);	
	for(int i=0; buf[i] != 0; i++)
	{
		Sleep(10);
		::PostMessage(h, WM_CHAR, buf[i], 0);
	}


	//click btn
	ClickOnRect(Rects.RaiseBtn);
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::Call()
{
	ClickOnRect(Rects.CallBtn);
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::Check()
{
	ClickOnRect(Rects.CallBtn);
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::Fold()
{
	ClickOnRect(Rects.FoldBtn);
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::AllIn()
{
	if(MyPos >= 0) 
		Raise(Brain.LastRaiseCount + PlayerInfo[MyPos].Stack);
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::GetMessage(TCHAR *oBuf)  
{
	if(MyPos < 0) 
	{
		_stprintf(oBuf, _T("no pos set"));
		return;
	}

	CString results[AiBrain::ACT_COUNT];
	results[AiBrain::ACT_FOLD] = _T("Decision: Fold");
	results[AiBrain::ACT_CALL] = _T("Decision: Call");
	results[AiBrain::ACT_CHECK] = _T("Decision: Check");
	results[AiBrain::ACT_ALL_IN] = _T("Decision: All in");
	results[AiBrain::ACT_ERROR] = _T("ERROR");
	results[AiBrain::ACT_RAISE].Format(_T("Decision: Raise by %d"), RaiseCnt);

	CString res;
	Brain.GetMessage(res.GetBuffer(10000));
	res.ReleaseBuffer();
	res += results[Action];

	_stprintf(oBuf, _T("%s"), res);
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::Think()
{
	if(MyPos < 0)
	{
		ObserverManager::GetInstance().UpdateDecision(_T("No position set"));
		return;
	}

	Action = Brain.MakeDecision(this, RaiseCnt);
	
	

	CString res;
	GetMessage(res.GetBuffer(1000));
	res.ReleaseBuffer();
	
	ObserverManager::GetInstance().UpdateDecision(res.GetBuffer());
}


//---------------------------------------------------------------------------------------------------------------------------------------
void AiPlayer::Play(CBotCore::Actions Action, int Stake)
{
/*
	switch(Action)
	{
	case AiBrain::ACT_CALL:
		this->Call();
		break;
	case AiBrain::ACT_CHECK:
		this->Check();
		break;
	case AiBrain::ACT_FOLD:
		this->Fold();
		break;
	case AiBrain::ACT_ALL_IN:
		this->AllIn();
		break;
	case AiBrain::ACT_RAISE:
		this->Raise(RaiseCnt);
		break;
	}
*/
	switch(Action)
	{
	case CBotCore::Actions::ACT_CALL:
		this->Call();
		break;
	case CBotCore::Actions::ACT_CHECK:
		this->Check();
		break;
	case CBotCore::Actions::ACT_FOLD:
		this->Fold();
		break;
	case CBotCore::Actions::ACT_ALL_IN:
		this->AllIn();
		break;
	case CBotCore::Actions::ACT_RISE:
		this->Raise(Stake);
		break;
	}

}


//---------------------------------------------------------------------------------------------------------------------------------------
AiPlayer::~AiPlayer()
{
}
